/*
 * KKAudioManager.cpp
 *
 *  Created on: 2013-9-15
 *      Author: wanghua
 */

#include "KKAudioManager.h"

KKAudioManager* KKAudioManager::m_audioManager = NULL;

KKAudioManager::KKAudioManager() {
	m_bgMusicPlayer = NULL;
}

KKAudioManager::~KKAudioManager() {
	stopBackgroudMusic();
	m_bgMusicPlayer = NULL;
}

void KKAudioManager::init() {
	KKAudioPlayer::initAudioSystem();

	CCDirector::sharedDirector()->getScheduler()->scheduleUpdateForTarget(this,
			0, false);
}

void KKAudioManager::update(float time) {
	KKAudioPlayer::updateAudioSystem();
}

void KKAudioManager::destory() {
	CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(
			this);
	KKAudioPlayer::destoryAudioSystem();
}

KKAudioPlayer* KKAudioManager::load(const char* soundPath) {
	KKAudioPlayer* player = m_audioCache.objectForKey(soundPath);

	if (!player) {
		player = new KKAudioPlayer();
		player->load(fullPathFromRelativePath(soundPath));
		m_audioCache.setObject(player, soundPath);
	}

	return player;
}

bool KKAudioManager::play(const char* soundPath, int loop,
		KKCallback* endCallback) {
	KKAudioPlayer* player = m_audioCache.objectForKey(soundPath);

	if (player) {
		player->setLoop(loop);
		player->setEndCallback(endCallback);
		player->rewind();
	} else {
		player = new KKAudioPlayer();
		player->load(fullPathFromRelativePath(soundPath));
		player->play(loop);
		player->setEndCallback(endCallback);
		m_audioCache.setObject(player, soundPath);
	}

	return true;

}

bool KKAudioManager::stop(const char* soundPath, bool cleanup) {
	KKAudioPlayer* player = m_audioCache.objectForKey(soundPath);

	if (player) {
		player->stop();
		if (cleanup) {
			player->destory();
			m_audioCache.removeObjectForKey(soundPath);
		}

	}

	return player;
}

bool KKAudioManager::pause(const char* soundPath) {
	KKAudioPlayer* player = m_audioCache.objectForKey(soundPath);

	if (player) {
		player->pause();
	}

	return player;
}

bool KKAudioManager::resume(const char* soundPath) {
	KKAudioPlayer* player = m_audioCache.objectForKey(soundPath);

	if (player) {
		player->resume();
	}

	return player;
}

float KKAudioManager::getDuration(const char* soundPath) {
	KKAudioPlayer* player = m_audioCache.objectForKey(soundPath);

	if (player) {
		return player->getDuration();
	}

	return -1;
}

float KKAudioManager::getVolume(const char* soundPath) {
	KKAudioPlayer* player = m_audioCache.objectForKey(soundPath);

	if (player) {
		return player->getVolume();
	}

	return 0;
}

bool KKAudioManager::setVolume(const char* soundPath, float volume) {
	KKAudioPlayer* player = m_audioCache.objectForKey(soundPath);

	if (player) {
		player->setVolume(volume);
	}

	return player;
}

void KKAudioManager::stopAll() {

	if (m_audioCache.begin()) {
		KKAudioPlayer* player = m_audioCache.next();

		while (player) {
			player->stop();
			player = m_audioCache.next();
		}
	}

}

void KKAudioManager::pauseAll() {

	if (m_audioCache.begin()) {
		KKAudioPlayer* player = m_audioCache.next();

		while (player) {
			player->pause();
			player = m_audioCache.next();
		}
	}

}

void KKAudioManager::resumeAll() {

	if (m_audioCache.begin()) {
		KKAudioPlayer* player = m_audioCache.next();

		while (player) {
			player->resume();
			player = m_audioCache.next();
		}
	}

}

void KKAudioManager::loadBackgroudMusic(const char* soundPath) {

	if (!m_bgMusicPlayer) {
		m_bgMusicPlayer = new KKAudioPlayer();
	}

	m_bgMusicPlayer->load(fullPathFromRelativePath(soundPath));
}

void KKAudioManager::playBackgroudMusic(const char* soundPath, int loop) {

	stopBackgroudMusic();

	if (!m_bgMusicPlayer || m_bgMusicPlayer->getSoundPath() != soundPath) {
		loadBackgroudMusic(soundPath);
	}

	m_bgMusicPlayer->play(loop);

}

void KKAudioManager::stopBackgroudMusic() {

	if (m_bgMusicPlayer) {
		m_bgMusicPlayer->stop();
		m_bgMusicPlayer->destory();
		CC_SAFE_DELETE(m_bgMusicPlayer);
	}
}

void KKAudioManager::pauseBackgroudMusic() {

	if (m_bgMusicPlayer) {
		m_bgMusicPlayer->pause();
	}
}

void KKAudioManager::resumeBackgroudMusic() {

	if (m_bgMusicPlayer) {
		m_bgMusicPlayer->resume();
	}
}

void KKAudioManager::setBackgroundVolume(float volume) {
	if (m_bgMusicPlayer) {
		m_bgMusicPlayer->setVolume(volume);
	}
}

void KKAudioManager::playEffect(const char* soundEffect) {
	KKAudioPlayer* player = m_audioCache.objectForKey(soundEffect);

	//CCLog("playEffect %s \n", soundEffect);

	if (player) {
		player->setSimple(true);
		player->setLoop(0);
		player->rewind();
	} else {
		player = new KKAudioPlayer();
		player->setSimple(true);
		player->load(fullPathFromRelativePath(soundEffect));
		player->play(0);
		m_audioCache.setObject(player, soundEffect);
	}

}

void KKAudioManager::playClickEffect() {
	playEffect("sounds/button_effect.mp3");
}

class SoundCallback: public KKCallback {
public:
	KKAudioPlayer* player;
	SoundCallback* nextCallback;
	string path;
public:
public:
	SoundCallback(KKAudioPlayer* player, string path,
			SoundCallback* nextCallback) :
			KKCallback(NULL, NULL, NULL) {
		this->player = player;
		this->path = path;
		this->nextCallback = nextCallback;
	}
	;

	virtual ~SoundCallback() {
		this->path.clear();
		CC_SAFE_RELEASE(this->player);
		CC_SAFE_RELEASE(this->nextCallback);
	}
	;

	virtual void call(CCObject* source = NULL) {

		if (nextCallback) {
			player->setEndCallback(nextCallback);
			player->load(
					CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile(
							"XXXXXXXXXXXXXXX", nextCallback->path.c_str()));
			player->play();
		} else {
			player->stop();
			player->release();
			player = NULL;
		}
	}

};

KKAudioPlayer* KKAudioManager::playSounds(const char* soundPath, ...) {
	va_list args;

	va_start(args, soundPath);

	const char* path = va_arg(args,const char*);

	SoundCallback* callback = NULL;

	SoundCallback* prevCallback = NULL;

	KKAudioPlayer* player = NULL;

	if (soundPath) {
		//	CCLog("playSounds = %s \n", soundPath);

		player = new KKAudioPlayer();

		player->setRemoveCallback(false);

		//player->autorelease();
		player->retain();

		player->load(fullPathFromRelativePath(soundPath));

		callback = new SoundCallback(player, soundPath, NULL);

		player->setEndCallback(callback);

		prevCallback = callback;
	}

	while (path) {

		callback = new SoundCallback(player, path, NULL);

		callback->autorelease();
		callback->retain();

		prevCallback->nextCallback = callback;

		prevCallback = callback;

		path = va_arg(args,const char*);

	}

	va_end(args);

	if (player) {
		player->play();
	}

	return player;
}
